package com.ydj.framework.resolver;

import com.ydj.framework.annotation.AllowGuest;
import com.ydj.framework.exception.VerifyTokenException;
import com.ydj.framework.filter.ExtHttpServletRequest;
import com.ydj.framework.redis.RdsBaseLoginInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.util.List;
import java.util.Objects;

/**
 * 真正的参数转换器
 *
 * @author Rick
 */
@Configuration
public class ExtArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private List<BaseArgumentResolver<?>> resolverList;

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        Class<?> parameterType = methodParameter.getParameterType();
        String parameterName = methodParameter.getParameterName();
        for (BaseArgumentResolver<?> resolver : resolverList ) {
            for (BaseArgumentResolver.ArgFormat argFormat : resolver.getArgFormatList()) {
                if (parameterType == argFormat.getArgType() && Objects.equals(parameterName, argFormat.getArgName())) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest webRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        Object nativeRequest = webRequest.getNativeRequest();
        if (!(nativeRequest instanceof ExtHttpServletRequest)) {
            return null;
        }

        ExtHttpServletRequest extRequest = (ExtHttpServletRequest) nativeRequest;
        RdsBaseLoginInfo info = extRequest.getInterceptorContext().getRdsLoginInfo();
        if (info == null) {
            if (methodParameter.getMethodAnnotation(AllowGuest.class) == null) {
                throw new VerifyTokenException();
            } else {
                return null;
            }
        }

        String parameterName = methodParameter.getParameterName();
        String uri = extRequest.getRequestURI();

        for (BaseArgumentResolver resolver : resolverList) {
            if (uri.startsWith(resolver.prePath())) {
                return resolver.doResolveArgument(parameterName, info);
            }
        }
        return null;
    }
}